# -*- coding: utf-8 -*-
# created on 2017/2/6

from mathsolver.functions.base import *
import requests
from sympy import *
from collections import defaultdict
from mathsolver.functions.sympy_utils import default_symbol, merge_known
from antlr4 import *
from mathsolver.mathparser.mathparserLexer import mathparserLexer
from mathsolver.mathparser.mathparserParser import mathparserParser
from mathsolver.mathparser.myparser import myparser

server_ip = "127.0.0.1:8008"
# server_ip = "172.30.12.34:8303"


class MathematicaSolveOld(BaseFunction):
    use_surd = True

    def __init__(self):
        super(MathematicaSolveOld, self).__init__()
        self.mapping = {}

    def interval_2_str(self, interval, e):
        """将区间转换成 Mathematica 的表达式 e.g. '-3 <= x < 0 || x > 1'"""
        if isinstance(interval, Interval):
            if interval.left != -S.Infinity and interval.right != S.Infinity:
                res = self.convert(interval.left) + (' < ' if interval.left_open else ' <= ') + e \
                      + (' < ' if interval.right_open else ' <= ') + self.convert(interval.right)
            elif interval.left == -S.Infinity:
                res = e + (' < ' if interval.right_open else ' <= ') + self.convert(interval.right)
            else:
                res = e + (' > ' if interval.left_open else ' >= ') + self.convert(interval.left)
        elif isinstance(interval, Union):
            res = "(%s)" % ' || '.join("(%s)" % self.interval_2_str(item, e) for item in interval.args)
        elif isinstance(interval, FiniteSet):
            res = "(%s)" % ' || '.join("(%s == %s)" % (e, str(item)) for item in interval.args)
        elif interval.is_real:
            res = "(%s == %s)" % (e, interval)
        else:
            raise ValueError('interval must be of type Interval or Union')

        return res

    @staticmethod
    def merge_answer(answer):
        key, item = list(answer.items())[0]
        if isinstance(item, list):
            item = FiniteSet(*item)

        key_is_number = defaultdict(list)
        for value in item:
            for k, v in zip(key, value):
                if not isinstance(v, Set) and not v.free_symbols:
                    key_is_number[k].append(1)
                else:
                    key_is_number[k].append(0)

        candidates = []
        new_item = []
        for value in item:
            cand = {}
            for k, v in zip(key, value):
                if not isinstance(v, Set) and any(key_is_number[k]) and not all(
                        key_is_number[k]) and k in item.free_symbols:
                    cand.update({k: v})

            if cand:
                candidates.append([cand, value])
            else:
                new_item.append(value)

        for value in new_item:
            for i, (cand, cand_v) in enumerate(candidates):
                value = value.subs(cand)
                if all([v1 == v2 or (isinstance(v1, FiniteSet) and len(v1) == 1 and list(v1)[0] == v2) for v1, v2 in
                        zip(value, cand_v)]):
                    pass

    def _eq(self, obj):
        return "==".join([self.convert(expr) for expr in obj])

    def _ineq(self, obj):
        return "".join([self.convert(expr) for expr in obj])

    def _ineqs(self, obj):
        return [self._eq(ineq) if all([op not in str(ineq[1]) for op in "<>!"]) else self._ineq(ineq) for ineq in
                obj.sympify()]

    def _list(self, obj):
        if len(obj) == 3:
            sym = sympify(obj[0]).subs(self.mapping)
            if obj[2] == "Integers":
                value = S.Integers
            else:
                value = sympify(obj[2]).subs(self.mapping)
            if obj[1] == "==":
                return sym, value
            elif ">" in obj[1]:
                return sym, Interval(value, S.Infinity, "=" not in obj[1])
            elif "<" in obj[1]:
                return sym, Interval(-S.Infinity, value, True, "=" not in obj[1])
            elif obj[1] == "Element":
                return sym, value
            else:
                return
        elif len(obj) == 5:
            sym = sympify(obj[2]).subs(self.mapping)
            return (sym.subs(self.mapping),
                    Interval(sympify(obj[0]).subs(self.mapping), sympify(obj[4]).subs(self.mapping), "=" not in obj[1],
                             "=" not in obj[3]))
        else:
            return

    def _and(self, obj):
        if any(isinstance(item, dict) for item in obj):
            ans = [self._or(item["Or"]) for item in obj]
            return merge_known(*ans)

        args = dict([self._list(item) for item in obj])
        if len(args) == 1:
            return args
        else:
            syms = args.keys()
            values = args.values()
            return {tuple(syms): tuple(values)}

    def _or(self, obj):
        values = defaultdict(list)
        key = None
        for ob in obj:
            if "And" in ob:
                ans = list(self._and(ob["And"]).items())[0]
            else:
                ans = self._list(ob)

            key, value = ans
            values[key].append(value)

        if not isinstance(key, tuple) and isinstance(values[key][0], Set):
            values[key] = Union(*[v if isinstance(v, Set) else FiniteSet(v) for v in values[key]])

        return values

    def make_answer(self, js):
        if "Or" in js:
            return self._or(js["Or"])
        elif "And" in js:
            return self._and(js["And"])
        elif js == "True":
            return S.Reals
        elif js == "False":
            return EmptySet()
        else:
            return dict([self._list(js)])

    def sympy2mathematica(self, obj):
        exprs = None
        if isinstance(obj, BaseEq):
            exprs = [self._eq(obj.sympify())]
        elif isinstance(obj, BaseEqs):
            exprs = [self._eq(eq) for eq in obj.sympify()]
        elif isinstance(obj, BaseIneq):
            exprs = [self._ineq(obj.sympify())]
        elif isinstance(obj, BaseIneqs):
            exprs = self._ineqs(obj)
        elif isinstance(obj, BaseOptimize):
            exprs = [self.convert(obj.sympify())]
        elif isinstance(obj, BaseOr):
            exprs = ["||".join(["(%s)" % "&&".join(self._ineqs(expr)) for expr in obj.exprs])]
        elif isinstance(obj, BaseBelong):
            if obj.value[-1] == "Z":
                exprs = ["Element[%s,%s]" % (self.convert(obj.value[0]), "Integers")]
            else:
                raise ValueError(obj.value[-1])

        exprs = [expr.replace(",", "，") for expr in exprs]
        return exprs

    def symbols_convert(self, syms):
        if isinstance(syms, (list, set)):
            return sorted([self.convert(sym) for sym in syms], key=lambda xx: xx[::-1])
        else:
            return self.convert(syms)

    def solver(self, *args):
        """如果无解 output[0].value 可能是 {x: EmptySet()}, {}"""
        # 输入为：BaseIneq, [BaseVariable, Interval/Union]
        exprs = self.sympy2mathematica(args[0])
        params = {"expr": exprs}
        if len(args) > 1 and args[1]:
            symbol = args[1].sympify()
            params["symbols"] = self.symbols_convert(symbol)
        if len(args) == 3:
            if isinstance(args[2], BaseBelong):
                params_cond = self.sympy2mathematica(args[2])
            else:
                cond_dict = args[2]
                params_cond = []  # cond 是 ['1 <= x <= E && a > 0'] 的格式， [] 可以去掉
                for sym, inter in cond_dict.items():
                    if inter != S.Reals:  # 如果 inter 为 (-oo, oo)，不需要考虑区间
                        from mathsolver.functions.hanshu.helper import interval_2_str
                        params_cond_i = self.interval_2_str(inter, self.convert(sym))
                        params_cond.append(params_cond_i)
            params["cond"] = ' && '.join(params_cond)
        # t = requests.get("http://127.0.0.1:8008/solve", params= params).json()
        body = '&&'.join(params["expr"]).encode()
        params.pop("expr")
        t = requests.post("http://%s/solvepost" % server_ip, data=body, params=params, timeout=8).json()
        if t == "True":
            self.output.append(BaseVariable(True))
        answer = self.make_answer(t)
        if isinstance(answer, Set):
            syms = args[0].free_symbols()
            answer = dict([(sym, answer) for sym in syms])
        else:
            answer = answer
        self.output.append(BaseSymbolValue(answer))
        return self

    def convert(self, res):
        if hasattr(res, "is_Symbol") and res.is_Symbol:
            if "_" in str(res):
                new_symbol = str(res).replace("_", "")
                self.mapping[Symbol(new_symbol)] = res
                return new_symbol

        if hasattr(res, "is_Add") and res.is_Add:
            expr = self.convert(res.args[0])
            for r in res.args[1:]:
                expr += " + " + self.convert(r)

        elif hasattr(res, "is_Mul") and res.is_Mul:
            expr = self.convert(res.args[0])
            for r in res.args[1:]:
                expr = "(%s) * (%s)" % (expr, self.convert(r))

        elif hasattr(res, "is_Pow") and res.is_Pow:
            if (1 / res.args[1]).is_Integer and self.use_surd:
                expr = "Surd[%s,%s]" % (self.convert(res.args[0]), self.convert((1 / res.args[1])))
            else:
                a, b = fraction(res.args[1])
                if str(b) != "1" and self.use_surd:
                    expr = "Surd[%s,%s]^(%s)" % (self.convert(res.args[0]), self.convert(b), self.convert(a))
                else:
                    expr = "(%s)^(%s)" % (self.convert(res.args[0]), self.convert(res.args[1]))

        elif hasattr(res, "is_Function") and res.is_Function:
            name = str(res.func)
            if "_" in name:
                if res.args[0].is_Symbol or res.args[0].is_Number:
                    new_symbol = ("%s%s" % (name, str(res.args[0]))).replace("_", "")
                    self.mapping[Symbol(new_symbol)] = res
                else:
                    new_symbol = "Subscript[%s,%s]" % (name.replace("_", ""), str(res.args[0]))

                expr = new_symbol
            elif name == "Root":
                expr = "%s[%s]" % (name, "&,".join([self.convert(r) for r in res.args]))
                expr = expr.replace("x", "#1")
            elif name in ["acos", "asin", "atan"]:
                name = name.replace("a", "")
                name = "Arc" + name[0].upper() + name[1:]
                expr = "%s[%s]" % (name, ",".join([self.convert(r) for r in res.args]))
            else:
                name = name[0].upper() + name[1:]
                if name == "Log":
                    expr = "%s[%s]" % (name, ",".join([self.convert(r) for r in res.args[::-1]]))
                else:
                    expr = "%s[%s]" % (name, ",".join([self.convert(r) for r in res.args]))
        else:
            transform_dict = {"pi": "Pi", 'oo': "Infinity", '-oo': "-Infinity"}
            expr = str(res)
            if expr in transform_dict:
                expr = transform_dict[expr]

        return expr


class MathematicaOptimize(MathematicaSolveOld):
    use_surd = False

    def convert_cond(self, obj_cond, var_symbol):
        if isinstance(obj_cond, (Interval, Union)):
            return [self.interval_2_str(obj_cond, self.convert(var_symbol))]
        elif isinstance(obj_cond, dict):
            return [self.interval_2_str(v, self.convert(k)) for k, v in obj_cond.items()]
        elif isinstance(obj_cond, list):
            return [item for cond in obj_cond for item in self.convert_cond(cond, var_symbol)]
            # params["cond"] = "&&".join([self.interval_2_str(obj_cond, self.convert(var_symbol))[0] if isinstance(
            #     obj_cond, (Interval, Union)) else self.toMathematica(cond)[0] for cond in obj_cond])
        else:
            return self.sympy2mathematica(obj_cond)

    def solver(self, *args):
        obj, syms = args

        math_expr = self.sympy2mathematica(obj)
        params = {"expr": math_expr, "flag": obj.flag}
        obj_cond = obj.cond

        var_symbol = default_symbol(sympify(obj.value))

        if not syms:
            params["symbols"] = self.symbols_convert(obj.free_symbols())
        else:
            params["symbols"] = self.symbols_convert(syms.sympify())

        if obj_cond:
            params["cond"] = self.convert_cond(obj_cond, var_symbol)
            # if isinstance(obj_cond, (Interval, Union)):
            #     params["cond"] = [self.interval_2_str(obj_cond, self.convert(var_symbol))]
            # elif isinstance(obj_cond, dict):
            #     params["cond"] = [self.interval_2_str(v, self.convert(k)) for k,v in obj_cond.items()]
            # elif isinstance(obj_cond, list):
            #     params["cond"] = "&&".join([self.interval_2_str(obj_cond, self.convert(var_symbol))[0] if isinstance(
            #         obj_cond, (Interval, Union)) else self.toMathematica(cond)[0] for cond in obj_cond])
            # else:
            #     params["cond"] = self.toMathematica(obj_cond)

        t = requests.get("http://%s/optimize" % server_ip, params=params, timeout=3).json()
        reachable = t["reachable"]
        ans = t["answer"]
        if isinstance(ans[0], str):
            self.output.append(BaseNumber(ans[0]))
            self.output.append(BaseSymbolValue(self.make_answer({"And": ans[1]})))
        else:
            self.output.append(ans[0])

        self.output.append(reachable)
        return self


class MathematicaSolve(MathematicaSolveOld):
    pass


class MathematicaSolve2(MathematicaSolveOld):
    def solver(self, *args):
        # 输入为：BaseIneq, [BaseVariable, Interval/Union]
        exprs = self.sympy2mathematica(args[0])
        exprs = "&&".join(exprs).replace("，", ",")

        # BaseVariable
        syms = ""
        if len(args) > 1:
            symbol = args[1].sympify()
            syms = "{%s}" % ",".join(self.symbols_convert(symbol))

        # Interval/Union (BaseIneq)
        if len(args) > 2:
            cond_dict = args[2]
            params_cond = []
            for sym, inter in cond_dict.items():
                if inter != S.Reals:  # 如果 inter 为 (-oo, oo)，不需要考虑区间
                    from mathsolver.functions.hanshu.helper import interval_2_str
                    params_cond = [interval_2_str(inter, str(sym))]

            exprs += "&&(%s)" % "||".join(params_cond)

        # print exprs,symbols
        t = requests.post("http://10.88.1.222:9000/api/v1/reduce", data={"expr": exprs, "symbols": syms})
        # print t.text
        lexer = mathparserLexer(InputStream(t.text))
        stream = CommonTokenStream(lexer)
        parser = mathparserParser(stream)
        tree = parser.token()
        visitor = myparser()
        visitor.mapping = self.mapping
        answer = visitor.visit(tree)
        if isinstance(answer, tuple):
            answer = dict([answer])
        elif isinstance(answer, list):
            answer = dict(answer)

        assert answer
        self.output.append(BaseSymbolValue(answer))
        return self


class MathematicaSimplify(MathematicaSolveOld):
    use_surd = False

    def solver(self, *args):
        expr = self.convert(args[0].sympify()).replace(",", "，")
        t = requests.get("http://%s/simplify" % server_ip, params={"expr": expr}, timeout=5)
        assert t.ok
        # print t
        answer = t.text
        # print answer
        self.output.append(BaseNumber(answer))
        return self


class MathematicaLimit(MathematicaSolveOld):
    """计算极限 
    
    调用例子：
        MathematicaLimit().solver(x**a, x, oo, direction='+', assumption={a: Interval(-oo, 0)})
        
    Mathematica Example: 
        Limit[x^a, x -> Infinity, Direction -> 1, Assumptions -> a < 0]
        Direction, Assumptions 可选
    """
    use_surd = False

    def solver(self, *args, **kwargs):
        # 输入
        expression, limit_symbol, limit_value = [self.convert(tt) for tt in args]

        # 极限 Direction
        if 'direction' in kwargs:
            direction_map = {'+': '-1', '-': '1', 'Automatic': 'Automatic'}
            direction = direction_map[kwargs['direction']]
        else:
            direction = 'Automatic'

        # 极限 Assumption
        if 'assumption' in kwargs:
            assumption_collector = []  # cond 是 ['1 <= x <= E && a > 0'] 的格式， [] 可以去掉
            for variable, interval in kwargs['assumption'].items():
                from mathsolver.functions.hanshu.helper import interval_2_str
                params_cond_i = self.interval_2_str(interval, self.convert(variable))
                assumption_collector.append(params_cond_i)

            assumption = ' && '.join(assumption_collector)
        else:
            assumption = None

        # Mathematica 表达式
        if assumption:
            mathematica_expr = 'Limit[%s, %s -> %s, Direction -> %s, Assumptions -> %s]' % \
                               (expression, limit_symbol, limit_value, direction, assumption)
        else:
            mathematica_expr = 'Limit[%s, %s -> %s, Direction -> %s]' % \
                               (expression, limit_symbol, limit_value, direction)

        mathematica_expr = mathematica_expr.replace(",", "，")
        t = requests.get("http://%s/limit" % server_ip, params={"expr": mathematica_expr}, timeout=5).text
        self.output.append(BasePoly(sympify(t)))
        return self


class MathematicaFindinstance(MathematicaSolveOld):
    def solver(self, *args):
        exprs = self.sympy2mathematica(args[0])
        params = {"expr": exprs, "symbols": self.symbols_convert(args[0].free_symbols())}

        # symbols
        if len(args) > 1:
            params["flag"] = str(args[1].value)
        else:
            params["flag"] = "1"

        t = requests.get("http://%s:8008/findinstance" % server_ip, params=params, timeout=5).json()
        answer = self.make_answer(t)
        if isinstance(answer, Set):
            syms = args[0].free_symbols()
            answer = dict([(sym, answer) for sym in syms])

        # print answer
        self.output.append(BaseSymbolValue(answer))
        return self


if __name__ == '__main__':
    stepsolver = MathematicaSolve().solver(BaseIneqs([["a_(1)**3*q**3 - 5", 0], ["a_(1)**3*q**21 - 10", 0], ["q", ">", "0"]]))
    # MathematicaSolve().solver(BaseIneq(["E**x + E**x*(-2 + x) + 2*a*(-1 + x)", ">", 0]))
    # MathematicaSolve().solver(BaseIneq(["2**(3*x) - 2**x", "<", "m*(2**x - 2**(-x))"]), BaseVariables([]))
    # MathematicaSolve().solver(BaseIneq(["2*(log(x, 1/2))**2 + 9 * log(x, 1/2) + 9", "<=", "0"]),
    #                           BaseVariable("x"))
    # MathematicaSolve().solver(BaseIneqs(
    #     [['x_1', '!=', 'x_2'], ['y_1', '!=', 'y_2'], ["y_1", "k*x_1 - 2*k + 2"], ["x_1**2 + y_1**2 - 8*y_1", 0],
    #      ["y_2", "k*x_2 - 2*k + 2"], ["x_2**2 + y_2**2 - 8*y_2", 0], ["2*x_3", "x_1 + x_2"], ["2*y_3", "y_1 + y_2"]]),
    #                           BaseVariables(["x_1", "y_1", "x_2", "x_3", "y_2", "y_3"]))
    # MathematicaOptimize().solver(BaseOptimize("sqrt(x_1**2 + (y_1 - 1)**2)", "Maximize",
    #                                           BaseIneqs([["a", ">", "1"], ["y_1**2 - 1 + x_1**2/a**2", 0]])), None)
    #
    # MathematicaOptimize().solver(BaseOptimize('a*b*c', "Maximize", BaseIneqs(
    #     [['a', '>', 0], ['a', '<', 1], ['b', '>=', 1], ['b', '<=', 8], ['c', '>=', 8],
    #      ['Abs(log(a))/log(2)', 'Abs(log(b))/log(2)', '-c/2 + 7']])), None)
    # MathematicaSolve().solver(BaseIneqs([["Abs(x+1/a) + Abs(x-a)", ">=", "2"]]))
    # MathematicaOptimize().solver(BaseOptimize("Abs(x+1/a)+Abs(x-a) - 2", "Minimize",
    #                                           BaseIneqs([["a", ">", "0"], ])), None).output[0].sympify()
    # result = MathematicaSolve().solver(BaseIneqs([['Abs(x+1/a) + Abs(x-a)', '>=', '2'], ['a', '>', '0']]),
    #                                    BaseVariable('x')).output
    # MathematicaOptimize().solver(BaseOptimize("Abs(x+1/a)+Abs(x-a) - 2", "Minimize",
    #                                           BaseIneqs([["a", ">", "0"], ])), None).output[0].sympify()
    # MathematicaOptimize().solver(BaseOptimize("Abs(x+1/a)+Abs(x-a) - 2", "Minimize",
    #                                           BaseIneqs([["a", ">", "0"], ])), None).output[0].sympify()
    # result = MathematicaSolve().solver(BaseIneqs([['2**x*(x-a)', '>=', '2'], ['a', '>', '0']]),
    #                                    BaseVariable('x')).output
    # MathematicaOptimize().solver(BaseOptimize("sqrt(3)*sin(pi*x/m)", "Minimize"),
    #                              None).output[0].sympify()
    # var = MathematicaOptimize().solver(BaseOptimize('a+b+a*b', "Minimize",
    #                                                 BaseIneqs([['a', '<', "-sqrt(2) - 1"], ['b', '>=', "-sqrt(2) - 1"],
    #                                                            ['b', '<=', "-1"],
    #                                                            ['a**2 + 2*a - 1', '-b**2 - 2*b + 1']])),
    #                                    None).output
    #
    # MathematicaSolve().solver(BaseIneq(['(2*x + 2*sign(x))/x', '<', '0']), BaseVariable('x'))
    # var = MathematicaSolve().solver(BaseIneq(['(-3*a + 2)/(x + 2)**2', '<', '0']), BaseVariables(["x"])).output
    # var = MathematicaSolve().solver(BaseEq([0, "x**2*log(a) - 2*x + 1"]), BaseVariables(["x", "a"])).output
    #
    # var = MathematicaSolve().solver(BaseIneq(['(-3*a + 2)/(x + 2)**2', '<', '0']), BaseVariables(["x"])).output
    # var = MathematicaSolve().solver(BaseEq([0, "x**2*log(a) - 2*x + 1"]), BaseVariables(["x", "a"])).output
    #
    # var = MathematicaSolve().solver(BaseIneq(['(-3*a + 2)/(x + 2)**2', '<', '0']), BaseVariable(["x"])).output
    # type(MathematicaSolve().solver(BaseIneq(['x + 2', '<', '0']), BaseVariables(["x"])).output[0].sympify())
    # var = MathematicaSolve().solver(BaseEq([0, "x**2*log(a) - 2*x + 1"]), BaseVariables(["x", "a"])).output
    # MathematicaSolve().solver(BaseIneqs([['k - 1/x', '>=', '0'], ['x', '>', 0]]), BaseVariable(['x'])).output[
    #     0].sympify()
    # MathematicaSolve().solver(BaseEqs([['A+B+C', 'Pi'], ['a/sin(A)', 'b/sin(B)'], ['b/sin(B)', 'c/sin(C)'],
    #                                    ['cos(A)', '(b**2 + c**2 - a**2)/(2*b*c)'],
    #                                    ['cos(B)', '(a**2 + c**2 - b**2)/(2*a*c)'],
    #                                    ['cos(C)', '(a**2 + b**2 - c**2)/(2*a*b)'], ['a*cos(B)', '3'],
    #                                    ['b*sin(A)', '4']]), BaseVariables(["a", "b", "c"]))
    #
    # var = MathematicaSolve().solver(BaseIneqs([['(-3*a + 2)/(x + 2)**2', '>=', '0']]),
    #                                 BaseVariable(['x'])).output[0].value
    # var = MathematicaSolve().solver(BaseIneqs([['-a + 3*x**2', '>=', '0']]), BaseVariable(['x'])).output[0].value
    # var = MathematicaSolve().solver(BaseEq(['c + x**3 - 3*x', '0']), BaseVariables(['c', 'x'])).output[0].value
    #
    # MathematicaOptimize().solver(BaseOptimize("(-x**2-4)/x", "Minimize",
    #                                           BaseIneqs([["x", ">=", "3"], ['4', ">=", "x"]])), None).output[
    #     0].sympify()
    #
    # var = MathematicaSolve().solver(BaseIneqs([["m - 2", '<', 0], ["m**2 - 9", '<', 0]])).output[0].value
    # var = MathematicaSolve().solver(BaseEq(['c + x**3 - 3*x', '0']), BaseVariables(['c', 'x'])).output[0].value
    # var = MathematicaSolve().solver(BaseEq(['c + x**3 - 3*x', '0']), BaseVariables(['c', 'x'])).output[0].value
    # var = MathematicaOptimize().solver(
    #     BaseOptimize("x**2", "Maximize",
    #                  BaseIneqs([["x", ">", "0"], ['x', "<", "1 "], ['x', '1/2']])), None).output[0].value
    # var = MathematicaOptimize().solver(
    #     BaseOptimize("x**2", "Maximize",
    #                  Interval(0, 1, True, True)), None).output
    #
    # var = MathematicaOptimize().solver(
    #     BaseOptimize("x**2", "Maximize", Union(Interval(0, 1),
    #                                            Interval(4, 5))), None).output
    #
    # var = MathematicaOptimize().solver(
    #     BaseOptimize("-m*x**2 - 4*m*x - m + 3", "Maximize"),
    #     BaseVariables(['x'])).output
    #
    # # 解方程测试
    # var = MathematicaSolve().solver(BaseEq(['x**2 - 4*x + 3', '0']), BaseVariables(['x']),
    #                                 {sympify('x'): Interval(-1, 2)}).output[0].value
    #
    # var = MathematicaSolve().solver(BaseIneqs([["m - 2", '<', 0], ["m**2 - 9", '<', 0]])).output[0].value
    # var = MathematicaSolve().solver(BaseEq(['c + x**3 - 3*x', '0']), BaseVariables(['c', 'x'])).output[0].value
    # var = MathematicaSolve().solver(BaseIneqs([['(-3*a + 2)/(x + 2)**2', '>=', '0']]),
    #                                 BaseVariable(['x'])).output[
    #     0].value
    # var = MathematicaSolve().solver(BaseIneqs([['-a + 3*x**2', '>=', '0']]), BaseVariable(['x'])).output[0].value
    # var = MathematicaSolve().solver(BaseIneq(['(-3*a + 2)/(x + 2)**2', '<', '0']),
    #                                 BaseVariables(["x"])).output[0].value
    # var = MathematicaSolve().solver(BaseEq([0, "x**2*log(a) - 2*x + 1"]),
    #                                 BaseVariables(["x", "a"])).output[0].value
    #
    # var = MathematicaSimplify().solver(BasePoly(x ** 2 + x - 2 * x)).output[0].value
    # MathematicaSolve().solver(BaseIneq(['a + x**2 + 2*x', '>=', '0']), BaseVariables(['x'])).output[0].printing()
    # MathematicaSolve().solver(BaseEq(['2*pi/Abs(x)', '2*pi']), BaseVariables(['x'])).output[0].sympify()
    # var = MathematicaSolve().solver(BaseEqs([["q**14*a_(1)**2 - 4", "0"], [
    #     "q**12*a_(1) + q**2*a_(1) - 5", "0"]]),
    #                                 BaseVariables(["q", "a_(1)"])).output[0].value
    #
    # var = MathematicaSolve().solver(BaseEqs([["q**14*a_(1)**2 - 4", "0"],
    #                                          ["q**12*a_(1) + q**2*a_(1) - 5", "0"]])).output[0].value
    #
    # var = MathematicaSolve().solver(BaseEqs([["x**2", "1"]]), BaseVariables(["x"])).output[0].value
    #
    # var = MathematicaSolve().solver(BaseEqs([["x**2", "1"]])).output[0].value
    # var = MathematicaSolve().solver(BaseIneqs([['exp(x) - 2 + exp(-x)', '>=', '0']]),
    #                                 BaseVariables(['x'])).output[0].value
    # var = MathematicaSimplify().solver(BaseNumber("oo*(-1)**(2/3)")).output[0].value
    # MathematicaSolve().solver(BaseIneq(['sin(x)', '>', '1/2']), BaseVariables(['x']))
    # var = MathematicaSolve().solver(BaseIneqs([['sin(x)', '>=', '0']]), BaseVariables(['x'])).output[0].value
    # var = MathematicaSimplify().solver(BaseNumber("log(3**(-n))/log(3)")).output[0].value
    # var = MathematicaSolve().solver(BaseEqs([[2 * pi, '2*pi/Abs(w)'], ['w*pi/4 + a', 'k*pi +pi/2']]),
    #                                 BaseVariables(['w', 'a'])).output[0].value
    # MathematicaSolve().solver(BaseEq(['cos(x)', '-sqrt(5)/5']), BaseVariable('x')).output[0].sympify()
    # var = MathematicaFindinstance().solver(BaseIneqs([["a", ">", "b", ">", "1"], ["0", "<", "c", "<", "1"]]),
    #                                        BaseNumber(2)).output[0].value
    # var = MathematicaSolve().solver(BaseEq(['x - sin(x)', '0']), BaseVariables(['x'])).output[0].value
    # var = MathematicaSolve().solver(BaseIneqs([["b_(n)", "1/(n*a_(n))"]]), BaseVariable("b_(n)")).output[0].value
    # var = MathematicaSolve().solver(BaseIneqs([["a_(n + 1)", ">", "0"],
    #                                            ["a_(n)", ">", "0"],
    #                                            ["-a_(n)**2 - 2*a_(n) + a_(n + 1)**2 - 2*a_(n + 1)", ">", "0"]]),
    #                                 BaseVariable("a_(n + 1)")).output[0].value
    # var = MathematicaSolve().solver(BaseIneqs([["a1 - 10", "0"], ("-3*d - a1", "<=", "0"),
    #                                            ("4*d + a1", "<=", "0")]),
    #                                 [],
    #                                 BaseBelong(["d + a1", '\\in', 'Z'])).output[0].value
    # var = MathematicaSolve().solver(
    #     BaseIneqs([["x_3**2 + y_3**2", 4], ["y_3", 0], ["x_4**2 + y_4**2", 4], ["y_4", 0]])).output[0].value
    # var = MathematicaSolve().solver(BaseIneqs([["(a-b)**2", "1"], ["a+b", "3"]])).output[0].value
    #
    # MathematicaSolve().solver(BaseIneqs(
    #     [['sqrt(3)*a - 2*c*sin(A)', '0'], ['c', '2'], ['a', '2*r*sin(A)'], ['b', '2*r*sin(B)'], ['c', '2*r*sin(C)'],
    #      ['sin(A)', '>', 0], ['sin(B)', '>', '0'], ['cos(A)', '(b**2 + c**2 - a**2)/(2*b*c)'],
    #      ['cos(B)', '(a**2 + c**2 - b**2)/(2*a*c)'], ['cos(C)', '(a**2 + b**2 - c**2)/(2*a*b)'],
    #      ['cos(A)**2 + sin(A)**2', '1'], ['sin(B)**2 + cos(B)**2', '1'], ['sin(C)**2 + cos(C)**2', '1']]),
    #     BaseVariables(['a', 'b', 'c', 'sin(A)', 'sin(B)', 'sin(C)', 'cos(A)', 'cos(B)', 'cos(C)'])).output[0].sympify()
    #
    # MathematicaSolve().solver(BaseIneqs(
    #     [['a_(n)**2 + 4*a_(n) - a_(n + 1)**2 + 4', '0'], ['a_(n)', '>', '0'], ['a_(n+1)', '>', '0']]),
    #     BaseVariable('a_(n + 1)')).output[0].sympify()
    pass
